\documentclass[10pt]{article}
\usepackage[spanish,activeacute]{babel}
\usepackage[utf8]{inputenc}
\usepackage{caratula}

\parskip    = 11 pt
\headheight	= 13.1pt


\title{Trabajo Práctico de Criptografía}
\author{Bernabé Panarello, Victoria Elizalde}



\begin{document}
%%---- Carátula -------------------------------------------------------------%%
\materia{Criptografía}
\titulo{Trabajo Práctico}

\integrante{Panarello, Bernabé}{194/01}{bpanarello@gmail.com}
\integrante{Elizalde, Victoria}{452/06}{kivielizalde@gmail.com}
\resumen{
}

% TOC, usa estilos locos
\maketitle
\tableofcontents
\newpage
\section{Enunciado}
Implementar un protocolo de comunicación con dos procesos que permita el envío de mensajes encriptados sin el conocimiento previo de información alguna, que no sea la dirección IP y el puerto de uno de ellos.

El protocolo debe ser capaz de completar un acuerdo de claves como paso previo a la comunicación propiamente dicha.

Documentar el protocolo, decisiones de implementación y manual de usuario. Explicar, si las hubiese, las falencias del protocolo, posibles ataques que pudieran resultar exitosos, debilidades y fortalezas. Se tendrá en cuenta especialmente la calidad de documentación y la estructura de la codificación.
\newpage
\section{Protocolo}
\subsection{Consideraciones generales}
El enunciado pide que dos procesos que no conocen nada el uno del otro (salvo ip y puerto) puedan mandarse mensajes encriptados. Es decir, el enunciado pide confidencialidad: que la información que intercambian pueda ser leída únicamente por ellos. La restricción de que los procesos no conocen nada del otro hace que no pueda existir un protocolo que asegure autenticación de las dos partes: nadie asegura que mi interlocutor es quien dice ser.
\subsection{Alternativas pensadas}
\subsubsection{Factorización del MCD}
Cada proceso calcula una m números primos al azar, los llamamos $p_{i}$. Luego calcula m números al azar (no hace falta que sean primos), $\alpha_{i}$. Esto que se calculó, representa la factorización de un número n: $n = \prod_{i = 1}^{m}p_{i}^{\alpha_{i}}$

Ambos procesos se intercambian sus respectivos números. La clave que usaran sera una función de la factorización del Máximo común divisor de ambos números. Habíamos pensado en usar por ejemplo la concatenación de los $p_{i}$ y $\alpha_{i}$: p1 $\|$ a1 $\|$ ... $\|$ pn $\|$ an (pero podría ser otra cosa, como por ejemplo $\varphi(mcd)$).

Si un intruso ve ambos números, puede calcular el MCD rápidamente con Euclides Extendido. Lo que no puede calcular fácilmente es la factorización del MCD. Por otro lado, cada uno de los procesos tiene una ventaja: conoce la factorización de alguno de los dos números. Los factores del MCD tienen que estar en la factorización de ambos números: entonces, cada proceso puede factorizar el MCD probando solamente con los primos que pertenecen a la factorización del número que él inventó.

\paragraph{Problemas}
Para que esto funcione, el MCD tiene que ser grande, y tiene que ser por lo menos producto de k primos, para que sea difícil de factorizar. Entonces, lo mas probable es que haya que repetir el proceso de ``inventar números'' infinitas veces, y que nunca encontremos un MCD aceptable.
\subsubsection{Diffie Hellman y AES}
Ya que nuestra idea claramente no iba a funcionar en la práctica, decidimos volver a un algoritmo más clásico, el que había inspirado nuestra idea: Diffie Hellman. La idea del algoritmo es establecer un canal seguro donde no lo hay. Para eso, el proceso A inventa 3 números: a, g y p. a es el número que se mantendrá en secreto, mientras los otros 2 son públicos.

\begin{figure}[h]
\centering
\includegraphics[scale=0.5]{diagramas/PNGs/DHclaves.png}
\caption{Acuerdo de claves entre Alice y Bob mediante Diffie-Hellman}
\end{figure}

A manda a B g, p y A = $g^{a}$ mod p. B inventa otro número, b, que también mantendrá secreto, y manda al proceso A el número B = $g^{b}$ mod p. Ahora ambos procesos pueden calcular la clave K = $A^{b}$ mod p = $B^{a}$ mod p.

Una vez que se negoció una clave entre ambos procesos, se encripta la comunicación usando un algoritmo simétrico con la clave negociada. Un buen algoritmo candidato es AES, parte del estándar en criptografía adoptado por el gobierno de Estado Unidos, el cual (a diferencia de DES) se considera seguro.

Como sólo A y B conocen la clave K, solo A y B podrán leer mensajes y solo A y B podrán escribirlos. Al no haber un mecanismo de autenticación, no hay certeza con que proceso establecí una comunicación, sí de que durante toda la comunicación el interlocutor es siempre el mismo.
\begin{figure}[h!]
\centering
\includegraphics[scale=0.5]{diagramas/PNGs/DHmensajes.png}
\caption{Intercambio de mensajes entre Alice y Bob}
\end{figure}
\paragraph{Problemas}
El problema de Diffie Hellman es que sin un mecanismo de autenticación es susceptible al ataque man-in-the-middle: un atacante E intercepta el mensaje enviado por A, y le responde con E = $g^{e}$ mod p, donde e es un número que ella inventó. Así obtiene la clave K para hablar con A: $A^{e}$.

\begin{figure}[h!]
\centering
\includegraphics[scale=0.5]{diagramas/PNGs/DHmimclaves.png}
\caption{Acuerdo de claves: Eve atacando a Alice y Bob (man-in-the-middle)}
\end{figure}

Por otro lado, E inventa un h, q y f. Manda a B h, q y F = $h^{f}$ mod q. B, pensando que está hablando con A, inventa un número b y envía B = $h^{b}$ mod q a E. E calcula K' como $B^{f}$ mod q y B como $F^{b}$ mod q.

Alice manda un mensaje a quien cree que es Bob (pero en realidad es Eve), encriptandolo con K, Eve lo desencripta y lo altera a su antojo, lo encripta nuevamente con K' y lo envía a Bob (haciéndose pasar por Alice).

Todo esto sucede porque A cree que habla con B, mientras que habla con E. Para evitar esto hace falta algún mecanismo de autenticación previo al Diffie Hellman, pero esto está necesariamente en contradicción con el enunciado, que dice que un proceso no puede conocer nada sobre el otro proceso. Una opción que pensamos para un eventual proceso de autenticación antes de usar Diffie Hellman sería usar certificados digitales.

\begin{figure}[h!]
\centering
\includegraphics[scale=0.5]{diagramas/PNGs/DHmimMensajes.png}
\caption{Intercambio de mensajes: Eve atacando a Alice y Bob (man-in-the-middle)}
\end{figure}

\subsubsection{RSA}
Otro algoritmo que consideramos para el protocolo es utilizar RSA. RSA es un algoritmo simétrico, en el cual cada proceso (en nuestro caso) genera un par de claves, una clave privada y una clave pública.

\begin{figure}[h]
\centering
\includegraphics[scale=0.5]{diagramas/PNGs/RSAclaves.png}
\caption{RSA: Alice y Bob intercambian sus claves públicas}
\end{figure}

Cada proceso envía al otro una clave del par que generó (la llamaremos pública, pero puede elegir cualquiera de las dos claves, matemáticamente no hay diferencia). Cada vez que alguien le quiera mandar un mensaje a un proceso, lo encriptará con la clave pública que generó ese proceso. Así, solo ese proceso será capaz de desencriptar el mensaje (confidencialidad), ya que la única forma de hacerlo es con la clave privada, que solo ese proceso conoce. 

\begin{figure}[h]
\includegraphics[scale=0.55]{diagramas/PNGs/RSAmensajes.png}
\caption{RSA: Alice envía un mensaje a Bob, Bob le responde}
\end{figure}

Por otro lado, como las claves públicas son, valga la redundancia, públicas cualquiera podría enviar un mensaje, haciéndose pasar por otra persona. Para evitar esto y asegurar autenticación, los mensajes enviados se encriptarán con la clave privada del emisor. Esto asegura que solo el emisor, que es quien tiene la clave pública pudo haber enviado ese mensaje.

En nuestro caso, teníamos a los procesos A y B que querían comunicarse entre sí. Como primer paso, A manda su clave pública a B y B manda su clave pública a A. Si A quiere mandar un mensaje a B, lo encripta con su clave privada, de forma de asegurar que lo envió A, ya que solo A conoce su clave privada y luego lo encripta con la clave pública de B, de forma que solo B pueda leer, porque solo B conoce su clave privada.

\paragraph{Problemas}

RSA también es susceptible al ataque man-in-the-middle. Supongamos nuevamente que un atacante E quiere interceptar la comunicación entre A y B. E intercepta la clave pública de A y la envía su clave pública, haciéndole creer que es la de B. Hace lo mismo con B: obtiene la clave pública de B y manda su clave pública, haciéndola pasar por la de A.

\begin{figure}[h]
\centering
\includegraphics[scale=0.5]{diagramas/PNGs/RSAmimclaves.png}
\caption{Intercambio de claves públicas: Eve atacando a Alice y Bob (man-in-the-middle)}
\end{figure}

De esta forma, cada vez que A manda un mensaje a E, E lo desencripta con su clave privada, lo modifica (eventualmente) y lo manda a B, encriptandolo con la clave pública de B. Ni A ni B se dan cuenta de lo que está sucediendo (no por el protocolo, al menos, ya que el ataque es totalmente transparente para ellos).

\begin{figure}[h]
\centering
\includegraphics[scale=0.45]{diagramas/PNGs/RSAmimmensajes.png}
\caption{Envío de mensajes: Eve atacando a Alice y Bob (man-in-the-middle)}
\end{figure}

Tenemos entonces el mismo problema que con Diffie Hellman. Al faltar un mecanismo de autenticación (debido a las restricciones del enunciado) no sé con quien estoy comunicandome.


\newpage
\subsection{Versión final del algoritmo}
Finalmente decidimos usar RSA con algunos cambios, ya que tanto RSA como Diffie-Hellman sufren del mismo problema: es posible un ataque man-in-the-middle. Si bien el enunciado nos limita bastante (como ya mencionamos) hay algunas cosas que podemos hacer.

\subsubsection{Autenticación y claves}
\paragraph{Autenticación}
Consideramos el problema de la autenticación, pese a que no se pedía en el enunciado. Nos pareció importante considerarlo en la discusión, sin embargo las mejoras propuestas acá no están implementadas.

Para lidiar con el problema de la autenticación, se nos ocurrió que podríamos confiar la primera vez que hablamos con alguien (como dijimos antes no tengo manera de corroborar su identidad si no conozco nada de esa persona antes), y luego las siguientes veces no podremos estar seguros de que estamos hablando con la persona correcta pero si sabremos que en todas las comunicaciones hablamos con la misma persona.

Finalmente nos enteramos que esto es lo que hace en realidad el protocolo SSH. Para lograr esto, decidimos que para cada proceso con el cual nos comunicamos, guardamos la clave pública de ese proceso. En la primera comunicación con ese proceso, no podremos corrobar nada, pero sí en las siguientes. Si al pedirle la clave pública a un proceso con el cual ya nos hemos comunicado en el pasado descubrimos que nos está dando otra, sospechamos que puede ser algún tipo de ataque y preguntamos al usuario que es lo que desea hacer al respecto, si confiar o no (como en SSH, que se avisa al usuario cuando un servidor cambia su fingerprint). El atacante podrida mentir y decir que su clave pública es la de el proceso a quien intenta suplantar (ya que esta clave es pública, posee la información), pero no le serviría de nada, ya que no conoce la clave privada asociada a esa clave pública y entonces nunca podría desencriptar los mensajes que recibe.

\paragraph{Cambio de claves}
Una de las decisiones que nos planteamos en el diseño del protocolo fue: ¿Proveemos un mecanismo para el cambio de claves? Decidimos que sí, que vamos a proveerlo, ya que nos parece que mandar muchos datos sin cambiar la clave deja abierta la posibilidad de que un atacante logre criptoanalizar nuestros mensajes.

Cada proceso decide cuando es oportuno cambiar su clave pública. Lo hace cuando haya transcurrido una determinada cantidad de tiempo (configurable) o haya transferido una determinada cantidad de bytes (también configurable), lo que ocurra primero.

Cuando un proceso decide que es momento de cambiar la clave, avisa a los otro(s) proceso(s) con los que se está comunicando en ese momento, enviando un mensaje que avisa que va a cambiar la clave. Es fundamental que los procesos receptores de este mensaje, puedan asegurarse de que el mismo es legítimo y no proviene de algún atacante que intenta reemplazar la clave pública del emisor por su clave pública para hacer un ataque man-in-the-middle.

El emisor manda entonces un mensaje de control que indica que de ahora en mas cambia la clave pública que se debe usar para desencriptar los mensajes. Manda además su clave pública actual encriptada con su clave privada actual (para autenticarse, es decir probar que el mensaje viene del legítimo emisor) y la clave pública nueva encriptada con su clave privada actual. La clave pública nueva se manda encriptada no por un tema de confidencialidad (no importa que se conozca, ya que es pública) sino porque si se mandara en claro un atacante podría interceptar el paquete y alterarlo, cambiando la nueva clave pública por una de su conveniencia.

Como definimos que las claves se van a cambiar continuamente, y avisar a todos los receptores el cambio de claves en el momento es imposible, los procesos tienen que guardar la última clave que usaron con cada proceso. De esa forma, inician la comunicación con la última clave pública que habían usado con ese proceso y una vez establecida la conexión, mandan el pedido de cambio de clave.

Entonces, cada proceso va a guardar: por un lado, las claves de todos los procesos con los cuales alguna vez se comunico, para constatar que sigue hablando con el mismo proceso; por otro lado, la ultima clave publica que uso con cada proceso para iniciar la comunicación con esa clave y ser correctamente identificado.

\subsubsection{Arquitectura y mensajes}
Nuestro protocolo está basado en la arquitectura cliente-servidor. Por un lado, tendremos un proceso que estará prendido en una determinada dirección, en un determinado puerto, al que llamaremos Servidor. Este proceso, recibirá pedidos de conexión por parte de otros procesos (que sólo conocen la dirección y el puerto donde está el Servidor), a quienes llamaremos Clientes.

Como se trata de un modelo Cliente-Servidor, es siempre el Cliente el que estable la conexión, y el único que envía mensajes y/o datos. El Servidor siempre responde los mensajes del Cliente, simplemente con un OK (indicando que todo estuvo bien), con un mensaje de error (si lo hubo) o un cambio de claves (ver a continuación).

\begin{figure}[h]
\centering
\includegraphics[scale=0.5]{diagramas/PNGs/intercambioClaves.png}
\caption{Intercambio de claves entre Cliente y Servidor}
\end{figure}

El Cliente empieza el intercambio de claves: pide al Servidor su clave pública, y envía su (del cliente) clave pública. El cliente guarda la clave pública del servidor: la necesitará de ahora en más para encriptar todas las comunicaciones para que sólo el Servidor sea capaz de desencriptar los datos que se manden. También necesitará esta clave para desencriptar las respuestas que envíe el Servidor (y constatar que efectivamente provienen del Servidor). Tanto el Cliente como el Servidor generan un par de claves para cada conexión.

Por otro lado, el Servidor guarda la clave pública del cliente, que usará para encriptar las respuestas que envíe al cliente (confidencidencialidad) y para desencriptar los que recibe de él (autenticación).

Una vez terminada la fase inicial de intercambio de claves, el Cliente puede enviar Datos al Servidor cuando lo desee, y también puede terminar la comunicación cuando lo desee (el Servidor no puede hacer ninguna de estas dos cosas).

En este modelo, el único que envía datos es el Cliente (encriptados con la clave pública del Servidor), por lo que nos pareció que el par de claves que valía la pena cambiar para evitar ser criptoanalizados es el del Servidor. Como el único que puede enviar mensajes es el Cliente, decidimos que el pedido del cambio de clave se haría como respuesta a un mensaje del Cliente. Esto se hará justo antes de enviar los datos (ver para mas detalle la sección de mensajes).

\begin{figure}[h]
\centering
\includegraphics[scale=0.5]{diagramas/PNGs/intercambioTexto.png}
\caption{El Cliente manda texto al Servidor}
\end{figure}

\paragraph{Mensajes del protocolo}
Todos los mensajes son enviados por el Cliente y son síncronicos. Las respuestas son enviadas por el Servidor.
Estos son los mensajes del protocolo:
\begin{itemize}
\item pk? El Cliente pregunta al Servidor su clave pública.
\item cpk?\{E:e, N:n\} Mensaje que el Cliente envía al Servidor, para informar su clave pública. 
\item begindata? Comienzo de un bloque de datos.
\item enddata? La contrapartida de begindata?, indica el fin del bloque de datos.
\item data?\{d: losDatos\} Un mensaje de datos.
\item quit Fin de la comunicación.
\end{itemize}
Y las respuestas:
\begin{itemize}
\item ok
\item pk!\{E:e, N:n\}El Servidor informa su clave pública.
\item rpk!\{clave: nuevaClave\} Cambio de clave pública. La nueva clave pública del Servidor es nuevaClave.
\end{itemize}
Los mensajes y las respuestas nunca van encriptados. Se encriptan únicamente los parámetros: por un lado, el cliente solo en cripta los datos con la privada del Cliente y luego con la pública del Servidor. El Servidor solo encripta el pedido de cambio de clave como aclaramos antes.

La respuesta rpk (cambio de claves) se envía como respuesta a un mensaje begindata?. Se envía en este momento porque el propósito del cambio de claves es evitar el criptoanálisis. Lo único que podría ser criptoanalizado, son los datos enviados por el cliente. Entonces, el chequeo se hace al momento de empezar el envío de un bloque de datos. El cliente sabe que después del begindata puede haber un cambio de claves, así que antes de enviar el siguiente dato, chequea la respuesta y cambia la clave si hace falta. Como los mensajes son sincrónicos, hasta que el Servidor no responda, no enviara datos.
\subsubsection{RSA: los pasos}
En esta sección hablaremos mas en detalle de RSA, para poder explicar detalles de implementación que tuvimos que resolver en nuestro protocolo. No veremos una demostración de porque RSA funciona, si no que solo hablaremos de los pasos del algoritmo, ya que esto repercute en la implementación. Veamos primero los pasos necesarios para generar un par de claves (una sera la publica y otra la privada):
\begin{enumerate}
\item Se eligen dos números primos (grandes) al azar. La forma de hacer esto es generar números al azar y luego usar un test de primalidad para ver si el numero generado es primo o no. Si no lo es, se sigue probando hasta encontrar uno que sea primo.
\item Se calcula n = p*q
\item Se calcula $\varphi$(pq) = (p-1)*(q-1) [Esto es así porque p y q son primos]
\item Se elige un numero e entre 1 y $\varphi$(pq) tal que ($\varphi$(pq),e) = 1 [Esto se hace para que e tenga inversa y exista el d del siguiente paso]
\item Encontrar d tal que: d * e $\equiv$ (mod $\varphi$(pq))
\end{enumerate}
Que significan todos estos números? Bueno, d y e son el par de claves, tomemos e como la publica y d como la privada (podría ser al revés también, es lo mismo). Puedo encriptar con cualquiera de las dos claves, y desencripto despues con la otra.

Para encriptar un numero m con la clave e la cuenta es la siguiente: \[ c\,=\,m^{e}\,mod\,\,n \] Para desencriptar c con la clave d: \[ m =\,c^{d}\,mod\,\,n\,\]

\paragraph{Que hacer con los números}
Ya dijimos que íbamos a usar el numero e como clave publica, así que claramente el numero e debe ser publico. De la cuenta para encriptar queda claro que el numero n también debe ser publico; d en cambio no lo difundo, ya que es la clave privada. Esto hace que solo el poseedor de d (que es quien genero las claves) es el único capaz de desencriptar los mensajes encriptados con d.

Los números p y q y $\varphi$(pq) hay que descartarlos. Si un atacante tuviera por e y $\varphi$(pq) podría calcular d, y quebrar el sistema. Si tuviera p y q, podría calcular $\varphi$(pq).

\subsubsection{RSA: detalles de implementación}
\paragraph{Strings vs Enteros}
Nuestro protocolo está pensado para enviar texto, entonces lo que queremos encriptar es texto. Sin embargo, lo que encripta RSA no es texto, sino números. ¿Cómo hacemos entonces la conversión de texto a números y viceversa?

Decidimos representar cada caracter con su correspondiente código ASCII (extendido). Entonces para transformar una cadena de texto se la transforma de esta manera:
AB = ascii(A) * \#ascii + ascii(B) = 65 * 256 + 66 = 16961. De esta forma identificamos unívocamente cada cadena de caracteres, de forma de que un número corresponde solo a una cadena de caracteres y viceversa.
\paragraph{Fraccionamiento de mensajes}
Antes mencionamos que se mandaban bloques de datos en distintos mensajes. En esta sección explicamos porque esto es así. Los mensajes son representados con números. Como la forma de encriptar un mensaje m es elevarlo a la e y luego calcular módulo n,m no debe ser mayor a n, es decir m puede tener largo  $<$ $log_{2}$(n) bits. Por este motivo, se parte el mensaje en partes que no superen esa longitud.

Al mismo tiempo, el mensaje tiene que tener una longitud mínima: si m es muy chico, $m^{e}$ = $m^{e}$ mod n. Para evitar que esto suceda, se rellena el mensaje con un caracter de padding (especificado en el archivo de configuración) para rellenar hasta llegar al largo mínimo.
\paragraph{Test de primalidad: Rabin-Miller}
Antes mencionamos que para buscar números primos en RSA se suele generar un numero al azar y luego testearlo con un teste de primalidad. Un test de primalidad, es un algoritmo que dado un numero, nos dice si este es primo o no. La diferencia con respecto a los algoritmos de factorización, es que no nos da la factorización, solo nos dice si es primo o no.

Nosotros decidimos utilizar un test de primalidad probabilístico: Rabin-Miller. Que el test sea probabilístico quiere decir que no puede asegurar que un numero p sea primo, pero si puede asegurar que p es primo con una cierta probabilidad q.

El test de Rabin-Miller se basa en la siguiente propiedad: Sea n es primo impar y n-1 = $2^{s}$*r con r impar. Sea a un entero coprimo con n, $\Rightarrow$ $a^{r}\equiv$1 (mod n) o $a^{2^{j}r}\equiv$ -1 (mod n) para algún j, $0\, \leq\,j\,\leq\,s-1$.

La idea de Rabin-Miller es la siguiente: 
\begin{enumerate}
\item Se elige un entero a en el intervalo [1, n - 1]
\item Si a $\neq$ 1 (mod n) y $a^{2^{j}r}\neq$ -1 (mod n) $\forall$ j, $0\, \leq\,j\,\leq\,s-1$, n no es primo
\item De lo contrario, no podemos asegurar nada (pero n es primo con una cierta probabilidad).
\item Mientras la \# iteraciones $<$ t, vuelvo a empezar
\end{enumerate}

Este método es iterativo, y la cantidad de iteraciones que se hagan es lo que determina cuanta seguridad tenemos de que un numero sea primo. Si se hacen t iteraciones (sin que se cumpla el punto 2) sabremos que la probabilidad de que n no sea primo es menor a $0.25^{t}$. El numero t representa claramente un trade-off: cuanto mas alto, mas seguridad tengo de que n es primo, pero mas tiempo tarda en correr el algoritmo. Por este motivo, en nuestro protocolo este numero es configurable (Ver archivo de Configuración).

Rabin Miller funciona solo para primos impares, por lo que lo antes de correr el test, verificamos que el numero no sea par (algo muy fácil de hacer).
\paragraph{Exponenciación Modular}
Se llama exponenciación modular a la operación entre enteros:
(x**y) mod n

En RSA, existen dos procedimientos que utilizan exponenciación modular:
\begin{itemize}
\item Algoritmo Rabin-Miller
\item Encriptación
\end{itemize}

En ambos casos, debe realizarse la exponenciación modular con números grandes (100 dígitos o mas). Realizar esta operación
directamente utilizando el operador ** del lenguaje de programación es impracticable para números de tal magnitud.
Por tal motivo, se debe utilizar otro algoritmo para llevar a cabo la exponenciación módulo n. El algoritmo que
hemos utilizado para tal fin en nuestra implementación es el de cuadrados sucesivos.

\paragraph{Chequeo automatico de integridad}
En nuestro protocolo, los mensajes se encriptan con la clave privada del emisor para asegurar que realmente provienen del emisor. Un atacante podría modificar el mensaje, solo que al no poseer la clave privada del emisor no tiene forma de mandar un cierto mensaje, solo puede modificar el mensaje y mandar "basura".

Si lo que se envía es texto, una persona rápidamente se da cuenta si fue alterado, porque no sería legible (en un programa se puede chequear las palabras contra un diccionario). Si el archivo enviado es binario, no hay forma de hacer este chequeo.

Como alternativa, se nos ocurrió que en cada chunk de datos, podemos incluir al principio de cada bloque una palabra conocida (configurable) de forma que al desencriptar los datos se puede chequear rápidamente si el mensaje esta corrupto o no (simplemente chequeando si al principio del mensaje aparece la palabra conocida o no).

De esta forma, se puede alertar al usuario si un mensaje fue modificado por un atacante.

\paragraph{Encriptación y firma}

A lo largo del TP, dijimos varias veces que cuando el Cliente manda un mensaje, primero lo firma con su clave privada y luego lo encripta con la clave publica del Servidor. En realidad, dijimos esto para simplificar las cosas en otras secciones en las que queriamos discutir otros temas, pero esto no es así.

El orden de estas dos operaciones no siempre es el mismo. Recordemos que encriptar con RSA significa elevar a una potencia y calcular modulo. Si firmamos el mensaje M con la clave F y lo encriptamos con la clave E estamos haciendo la siguiente cuenta:
\[ C =\,M^{F}\,mod\,\,N\,\]
\[ C' =\,C^{E}\,mod\,\,N'\,\]

Si N $<$ N' no hay ningún problema. Sin embargo, si N fuera mayor, C $>$ N'. Entonces, para evitar eso, si N $>$ N'. primero se firma y luego se encripta, de lo contrario el orden se invierte.

La parte de padding, separar el mensaje y el agregado de la palabra para chequear integridad, se hacen siempre antes, independientemente de si el cliente firma con su clave primero o primero encripta con la clave del Servidor.

El Servidor también compara N y N' y en base a eso decide en que orden tiene que desfirmar/desencriptar.
\newpage 
\section{Manual de Usuario}
\subsection{Requisitos}
Nuestro tp usa Python 2.6 y la librería jsonpickle. Para instalar ambas cosas en Linux instalar los siguientes paquetes con el package manager de su preferencia:
\begin{itemize}
\item python2.6
\item python-jsonpickle
\end{itemize}
En Windows:
\begin{itemize}
\item Instalar python2.6
\item En la carpeta lib, python setup.py install
\end{itemize}
\subsection{Uso}
El protocolo está pensado únicamente para mandar texto. No es posible mandar archivos binarios así como está. Si el usuario quiere enviar archivos binarios, se sugiere encodear el binario a base64, enviarlo y luego desencodearlo.

a) Inicialización del servidor
Para iniciar una instancia del servidor, el usuario debe ingresar el siguiente comando en la consola:

 python server.py

Esto inicializará una instancia de servidor capaz de atender múltiples clientes.
Los datos recibidos desde los clientes son volcados a la salida standard (stdout).

b) Conectarse a un servidor

Para conectarse a un servidor debe ejecutarse el siguiente comando:

 cssendfile $<$host$>$ $<$port$>$ $[$outfile$]$

donde:
  host: Es el nombre o dirección IP del host donde se ejecuta una instancia del server
  port: Puerto donde esta escuchando el server
  outfile: Parámetro opcional que especifica al server el nombre de archivo de salida donde deben volcarse 
  los datos recibidos. Si no se especifica, el server enviará los datos a la salida standard.
  
Al ejecutarse el comando cssendfile, se intentará realizar la conexión TCP con el servidor y el posterior
handshake (intercambio de claves públicas). Si el handshake resulta exitoso, cssendfile procede a encriptar y 
enviar los datos presentes en al entrada standard (stdin). Esto quiere decir que es posible enviar un archivo en forma
segura a un server de la siguiente manera:

En UNIX:

 cat iliada.txt | python cssendfile seguro.dc.uba.ar 50009

En Windows:

 type iliada.txt | cssendfile.bat seguro.dc.uba.ar 50009

La necesidad de utilizar un bat en Windows es debida a un bug en el sistema de pipes, por el cual
no es posible redirigir la salida de un proceso a un comando del tipo $<$exe$>$ + $<$archivo asociado$>$, por lo que es necesario
empaquetar ``python cssendfile'' en un comando simple, cssendfile.bat.

Como se señaló anteriormente, solamente esta soportado el envío de texto (caracteres imprimibles), por lo que si se requiere
enviar otro tipo de archivo, el mismo deberá ser convertido previamente a un formato como Base64.
Esto podría realizarse en la misma línea de comandos, utilizando una utilidad como la encontrada en 

http://www.fourmilab.ch/webtools/base64/

Ejemplo: Enviar el archivo foto.jpg encriptado a un servidor

 base64 -e foto.jpg foto.jpg.64
 cat foto.jpg.64 | python cssendfile seguro.dc.uba.ar 50009
\subsection{Archivo de configuración}
En el archivo de configuración se encuentran algunas variables que por distintos motivos son candidatas a ser modificables. El archivo esta dividido en dos partes: RSA y Network. El archivo se encuentra con el resto del código, se llama csushi.cfg.

Al principio, hay unos valores que corresponden a la busqueda de primos (p y q) para generar claves. Por un lado, aparece el intervalo en el cual se van a buscar primos. Mas atrás dijimos que se generaban números al azar y luego se testeaba primalidad: bueno, los números se buscaran en este rango. La seguridad de RSA depende de que los primos sean grandes, pero cuanto mas grandes sean los primos, mas se tardara en hacer las cuentas. Como esto es un trade-off, dejamos valores que consideramos razonables y damos al usuario la posibilidad de modificarlos.

Por otro lado, siguiendo en tema de números primos, se pueden configurar la cantidad de iteraciones de Rabin-Miller. Como mencionamos antes: a mas iteraciones menor probabilidad de que el numero no sea primo (y sea declarado primo), pero mas tiempo tarda el algoritmo en correr.

Por otro lado, hay otras configuraciones un poco mas relativas a nuestro protocolo: el caracter usado para padding (código ASCII expresado en decimal) y la palabra que se usa para chequear integridad automáticamente.

Finalmente, en la parte de network se puede configurar en que puerto se levantara el servidor.

El archivo esta apropiadamente comentado, y los nombres de las variables son razonables, así que creemos que no hace falta mayor explicación que esta, es muy fácil de modificar.
\subsection{Módulos}
La solución esta compuesta por los siguientes módulos python:
\begin{itemize}
\item cliente.py: Modulo que contiene la clase Cliente. Maneja la conexión y handshake con el servidor
y expone una API para envío de texto encriptado.
\item configurator.py: Provee al resto de los módulos acceso al archivo de configuración
\item csrsa.py: Implementa toda la funcionalidad RSA: Generación de claves, encriptación/desencripción y encripción de texto
\item cssendfile.py: Programa cliente.
\item dbg.py: Expone un método para logear en forma condicional a la stdout.
\item server.py: Servidor. Implementa una clase socket-server que atiende y resuelve los requests de los clientes
\item str2int.py: Implementa la funcionalidad que permite convertir texto en números y viceversa.
\end{itemize}
\end{document}